Migrating to Mongoose 8
mongoose 7からmongoose 8への変更点
2025年6月に書いたページを/Nota/Migrating to Mongoose 8からコピペしたshokai.icon
Mongoose v8.15.1: Migrating to Mongoose 8
書かれている全項目を調査したshokai.icon
Cosenseのmongooseを8.x系最新版に上げるのため
20250616-012050.txt by Claude Code.iconshokai.icon
Cosenseの実装と読み合わせする、ドキュメントとコードの読み合わせ機になってもらった
https://mongoosejs.com/docs/migrating_to_8.html を読んで、上から順に1つずつmigration内容を確認し
このリポジトリ内の実装と照らし合わせて1つずつレポートしてください。
migration内容を私に説明しつつ、現在の実装に問題が無いか調査してくれ、という事です。
コードの変更は最後にまとめて行うので、まだやらなくていいです
https://app.devin.ai/sessions/b12f8aa362424daca439a7136c5f191a by Devin.iconshokai.icon
Deep Agent modeで開始
既にnpm自体はmongoose 8に更新してしまったのですが、migration guideの内容について改めて確認したい
https://mongoosejs.com/docs/migrating_to_8.html を読んで、上から順に1つずつmigration内容を確認し
このリポジトリ内の実装と照らし合わせて1つずつレポートしてください。
migration内容を私に説明しつつ、現在の実装に問題が無いか調査してくれ、という事です。
コードの変更は最後にまとめて行うので、まだやらなくていいです
リズム合わなすぎてキツくなってきたshokai.icon
Devinの作業中でも非同期にchat入力できるというコンセプトがshokaiの逐次作業のリズムと合わない
Removed rawResult option for findOneAndUpdate()
使用箇所無し
Document.prototype.deleteOne now returns a query
deleteOneの返り値が変わった
これまでは削除したdocument数が返っていたが
DeleteResult objectが返るようになった
Migrating to Mongoose 6で掲載されて無くて、mongooseを5から6に更新したらScrapboxの同時編集が永遠にコンフリクト解消できなくなったの原因になったupdateOneの返り値変更と同じやつだshokai.icon
まあ、deleteOneの返り値を使う処理はしていないので問題ないのですが
MongoDB Node Driver 6
mongoose 8系はMongoDB Node Driver v6.xを使用するが、
MongoDB Node Driver v6.17ではMongoDB 4.0のサポートが削除されている
https://github.com/mongodb/node-mongodb-native/releases/tag/v6.17.0
/help-enterprise-jp/MongoDBの更新#6734445997c29100002846ea
オンプレ版は既に5.0以上が必要になっているので、4.0のサポートが削除されても問題ナシohnishiakira.icon
12桁のObjectIdのサポートが打ち切られ、new mongoose.Types.ObjectId('12charstring')がthrow errorされるようになった
これまでimportできてたJSONがimportできなくなる可能性はあるが
それはそのJSONがおかしいだけなので問題なし
Claude Codeはこの部分等に直接例外処理を挿入して、エラーを握りつぶそうとしてくる
code:src/server/models/project/json-import.ts
if (Array.isArray(files)) {
page.files = uniq(files).map(file => new mongoose.Types.ObjectId(file));
}
AIコーディングエージェントには大局観が無い。例外は発生させて良い。呼び出し元で例外処理しているのだから
不正なデータが入力されたら、ユーザーに「不正なデータです」と報告するべき
処理できる所だけ処理して、ダメだった所を握りつぶして報告しないのは本当にダメ
一方Devin.iconはこれを自発的に発見してくれなかったので、ドキュメントとコードの読み合わせ機としてちょっと良くないなshokai.icon
Removed findOneAndRemove()
使用箇所無し
Removed count()
使用箇所無し
Removed id Setter
使用箇所無し
doc.id = '0'.repeat(24)
_idを更新していいものだと思ってなかったので、これ可能だったんだと驚いたshokai.icon
null is valid for non-required string enums
使用箇所無し
type: Stringかつenumのfieldに、nullを保存できるようになった
mongoose 7まではnullを保存できなかった
required: trueを指定すると、nullを保存できなくなる
まあこれはこの方が正しい挙動なような気もするshokai.icon
Apply minimize when save() updates an existing document
save時に値が空Object、つまり{}のfieldは、undefinedとして保存されるようになった
つまりproject.additionalPlans.kcsのようなnested fieldの参照は
Cosense for KCSの有効化で設定解除方法として説明しているような
% db.projects.updateOne({ nameLc: 'nota' }, { $unset: {'additionalPlans.kcs': true} })
という方法だと
additionalPlans: {}になる可能性があるので
MongoDBにsaveした時点で.additionalPlans: undefinedになる
対応
常にnull checkする
あるいはmongooseのdefault機能を使って、DB上でundefinedだったらnode.js上では{}をセットする
Cosenseではこっちを採用しているshokai.icon
project.addionalPlansにデフォルト値として {} を持たせる & server側のみnull check削除 #7317
Apply base schema paths before discriminator paths
使用箇所無し
こんな気持ち悪い多重継承みたいな機能あったんだshokai.icon
Removed overwrite option for findOneAndUpdate()
使用箇所無し
Changed behavior for findOneAndUpdate() with orFail() and upsert
使用箇所無し
create() waits until all saves are done before throwing any error
使用箇所無し
createには複数の引数を渡すと、複数のdocumentを作成できる
mongoose 7では先頭から順に保存される。失敗した所から後ろは保存されない
mongoose 8では、引数のうち1つが失敗しても、その後のdocumentは保存される
Model.validate() returns copy of object
使用箇所無し
Modelのstatic methodのvalidateの挙動が変更された
save時に自動呼び出しされるvalidatorではない
validate対象のobjectを変更してしまう事があったらしい
Allow null For Optional Fields in TypeScript
明示的に使用している箇所は無いはずshokai.icon
mongoose 7では、例えばtype Stringのfieldにはstringとundefinedしか保存できなかった
mongoose 8では、stringとundefinedとnullを保存できる
元々MongoDBってnullもundefinedも保存できるものだし
そういう値が入っている事を前提にアプリケーションコードを書くか
入らないようにmongoose custom validatorsやrequired: trueで保護しているので、問題ないだろうshokai.icon
Model constructor properties are all optional in TypeScript
よくわからんshokai.icon
Cosenseのmongoose modelのTypeScript化ガイドの形式に似てるけど、_idとかはschemaに書かなくても良くなったという事?
Infer distinct() return types from schema
単にmongodb distinctで型情報が返るようになっただけなので、特に対応作業は必要無しshokai.icon